package cn.iocoder.yudao.module.alipay.didi.client.impl;

import cn.iocoder.yudao.module.alipay.didi.auth.Auth;
import cn.iocoder.yudao.module.alipay.didi.auth.Uuid;
import cn.iocoder.yudao.module.alipay.didi.client.BasicClient;
import cn.iocoder.yudao.module.alipay.didi.common.Constants;
import cn.iocoder.yudao.module.alipay.didi.models.DunionClientConfig;
import com.google.gson.Gson;
import org.slf4j.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.TreeMap;

public class BasicClientImpl implements BasicClient {

    private static final Logger LOGGER = Constants.dunionClientLogger;

    private static final String DIDI_HEADER_RID = "Didi-Header-Rid";

    private static final String USER_AGENT = "User-Agent";
    private static final String SDK_VERSION = "dunion-go-openapi-sdk-1.0";

    @Override
    public String doPost(DunionClientConfig dunionClientConfig, String urlPath, int timeout, TreeMap<String, Object> params){
        HttpURLConnection connection = null;
        StringBuilder msg = new StringBuilder();
        TreeMap<String, Object> headers = new TreeMap<>();
        try {
            LOGGER.info("doPost start, dunionClientConfig:{}, urlPath:{},timeout:{}, params:{}", dunionClientConfig.toString(), urlPath, timeout, params.toString());
            headers.put("App-Key", dunionClientConfig.getAppKey());
            headers.put("Timestamp", (int) (System.currentTimeMillis() / 1000));
            String sign = Auth.genSign(headers, params, dunionClientConfig.getAccessKey());

            //增加traceId
            headers.put(DIDI_HEADER_RID,  Uuid.getUUID());

            URL url = new URL(urlPath);
            connection = (HttpURLConnection) url.openConnection();

            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty(USER_AGENT, SDK_VERSION);

            // 设置是否向HttpURLConnection输出
            connection.setDoOutput(true);
            // 设置是否从httpUrlConnection读入
            connection.setDoInput(true);
            // 设置是否使用缓存
            connection.setUseCaches(false);
            connection.setRequestProperty("Sign", sign);
            for (String key : headers.keySet()) {
                connection.setRequestProperty(key, headers.get(key).toString());
            }
            // 设置超时时间
            int configTimeout = dunionClientConfig.getTimeout();
            if(timeout != 0){
                configTimeout = timeout;
            }
            connection.setConnectTimeout(configTimeout);
            // 连接
            connection.connect();

            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8));
            String json = new Gson().toJson(params);
            writer.write(json);
            writer.close();

            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            out.flush();
            out.close();

            // 得到响应状态码的返回值 responseCode
            int code = connection.getResponseCode();
            // 正常响应
            if(code == 200){
                // 从流中读取响应信息
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                // 循环从流中读取
                while ((line = reader.readLine()) != null) {
                    msg.append(line).append("\n");
                }
                // 关闭流
                reader.close();
            }
            // 显示响应结果
            LOGGER.info("doPost get result, urlPath:{}, configTimeout:{}, headers:{}, msg:{}", urlPath, configTimeout, headers, msg);
        }catch (Exception e){
            LOGGER.error("doPost error, urlPath:{}, headers:{}, error:{}", urlPath, headers, e.getMessage());
        }finally {
            // 5. 断开连接
            if (null != connection){
                try {
                    connection.disconnect();
                }catch (Exception e){
                    LOGGER.error("doPost connection close error, urlPath:{}, headers:{}, error:{}", urlPath, headers, e.getMessage());
                }
            }
        }
        return msg.toString();
    }

    @Override
    public String doGet(DunionClientConfig dunionClientConfig, String urlPath, int timeout, TreeMap<String, Object> params) {
        HttpURLConnection connection = null;
        StringBuilder msg = new StringBuilder();
        TreeMap<String, Object> headers = new TreeMap<>();
        try{
            LOGGER.info("doGet start, dunionClientConfig:{}, urlPath:{}, timeout:{}, params:{}", dunionClientConfig.toString(), urlPath, timeout, params.toString());
            headers.put("App-Key", dunionClientConfig.getAppKey());
            headers.put("Timestamp", (int) (System.currentTimeMillis() / 1000));
            String sign = Auth.genSign(headers, params, dunionClientConfig.getAccessKey());

            //traceId
            String uuid = Uuid.getUUID();
            headers.put(DIDI_HEADER_RID, uuid);

            StringBuilder sb = new StringBuilder();
            sb.append(urlPath);
            sb.append("?");
            for (String key : params.keySet()) {
                sb.append("&").append(key).append("=").append(params.get(key));
            }

            String str = sb.toString().replaceFirst("&", "");
            URL url = new URL(str);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            // 设置是否向HttpURLConnection输出
            connection.setDoOutput(true);
            // 设置是否从httpUrlConnection读入
            connection.setDoInput(true);
            // 设置是否使用缓存
            connection.setUseCaches(false);
            // 设置超时时间
            int configTimeout = dunionClientConfig.getTimeout();
            if(timeout != 0){
                configTimeout = timeout;
            }
            connection.setConnectTimeout(configTimeout);

            connection.setRequestProperty("Sign", sign);//设置参数类型是json格式
            for (String key : headers.keySet()) {
                connection.setRequestProperty(key, headers.get(key).toString());
            }
            connection.setRequestProperty(USER_AGENT, SDK_VERSION);
            connection.connect();

            // 如果返回值正常，数据在网络中是以流的形式得到服务端返回的数据
            if (connection.getResponseCode() == 200) {
                // 从流中读取响应信息
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                // 循环从流中读取
                while ((line = reader.readLine()) != null) {
                    msg.append(line).append("\n");
                }
                reader.close(); // 关闭流
            }
            // 显示响应结果
            LOGGER.info("doGet get result, urlPath:{}, configTimeout:{}, headers:{}, msg:{}", urlPath, configTimeout, headers, msg);
        }catch (Exception e){
            LOGGER.error("doGet error, urlPath:{}, headers:{}, error:{}", urlPath, headers, e.getMessage());
        }finally {
            // 断开连接，释放资源
            if (null != connection){
                try {
                    connection.disconnect();
                }catch (Exception e){
                    LOGGER.error("doGet connection close error, urlPath:{}, headers:{}, error:{}", urlPath, headers, e.getMessage());
                }
            }
        }
        return msg.toString();
    }
}
